package com.tuo51.core.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.tuo51.components.redis.RedisService;
import com.tuo51.core.domain.org.Organization;
import com.tuo51.core.domain.staffs.Staff;
import com.tuo51.core.domain.staffs.StaffExtInfo;
import com.tuo51.core.repositories.OrgnizationRepository;
import com.tuo51.core.repositories.StaffExtInfoRepository;
import com.tuo51.core.repositories.StaffRepository;
import com.tuo51.core.service.StaffService;
import com.tuo51.evaluate.repositories.LoginRecordRepository;
import com.tuo51.evaluate.service.ChildrenService;
import com.tuo51.evaluate.service.EvaluateV2Service;
import com.tuo51.evaluate.service.sms.SmsService;
import com.tuo51.foudation.constant.CommonConstant;
import com.tuo51.foudation.exception.BusinessException;
import com.tuo51.foudation.model.ErrorCode;
import com.tuo51.foudation.model.MemVerificationCache;
import com.tuo51.foudation.utils.ModelUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;


/**
 * *******************************
 * Created by Tim.
 * form com.matt
 * on 2018/5/21
 * *******************************
 */
@Transactional
@Service
@Slf4j
public class StaffServiceImpl implements StaffService {

    @Autowired
    private StaffRepository staffRepository;

    @Autowired
    private StaffExtInfoRepository staffExtInfoRepository;

    @Autowired
    private OrgnizationRepository orgnizationRepository;

    @Autowired
    private LoginRecordRepository loginRecordRepository;

    @Autowired
    private EvaluateV2Service evaluateV2Service;

    @Autowired
    private ChildrenService childrenService;

    @Autowired
    RedisService redisService;

    @Autowired
    private MemVerificationCache cache;

    @Autowired
    private SmsService smsService;

    @Value("${spring.profiles.active}")
    private String PROFILE_ACTIVE;

    @Value("${partners.appid_mapping.family}")
    private String MP_SOURCE_ID;

    @Value("${partners.appid_mapping.org}")
    private String MA_SOURCE_ID;

    @Override
    public boolean modifyHeadImg(String staffId, String imgUrl) {
        Staff staff = staffRepository.getOne(staffId);
        staff.setHeadImgUrl(imgUrl);
        staffRepository.save(staff);
        return true;
    }

    @Override
    public boolean modifyAreaLogo(String staffId, String areaLogo){
        Staff staff = staffRepository.getOne(staffId);

        Organization org = staffOrgnization(staff);

        org.setLogo(areaLogo);

        orgnizationRepository.save(org);

        return true;
    }

    @Override
    public Staff getById(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new BusinessException(ErrorCode.STAFF_NOT_EXIST, "用户不存在");
        }
        return staffRepository.getOne(id);
    }

    @Override
    public Staff mpUserByPartnerUserId(String partnerUserId){
        return userByPartnerUserId(partnerUserId, MP_SOURCE_ID, CommonConstant.Platform.WXMP);
    }

    @Override
    public Staff maUserByPartnerUserId(String partnerUserId){
        return userByPartnerUserId(partnerUserId, MA_SOURCE_ID, CommonConstant.Platform.WXMA);
    }

    private Staff userByPartnerUserId(String partnerUserId, String appid, CommonConstant.Platform platform){
        if (StringUtils.isEmpty(partnerUserId)) {
            throw new BusinessException(ErrorCode.STAFFID_NEEDED, "参数错误");
        }
        Staff partnerStaff = staffRepository.getOne(partnerUserId);
        String unionId = partnerStaff.getUnionid();
        if (StringUtils.isEmpty(unionId)) {
            throw new BusinessException(ErrorCode.UNEXPECTED_ERROR, "预料之外的错误：unionId为空");
        }
        Staff staff = staffRepository.getByUnionidAndIdNotAndSourceAppId(unionId, partnerUserId, appid);
        if (staff == null) {
            // 创建占位账号
            staff = add(null, null, unionId, null, appid, platform);
            staff.setNickName(partnerStaff.getNickName());
            staff.setHeadImgUrl(partnerStaff.getHeadImgUrl());
            staff.setSex(partnerStaff.getSex());
            staff.setMobile(partnerStaff.getMobile());
            staff.setSexDesc(partnerStaff.getSexDesc());
            staff.setTemporally(true);
            staffRepository.save(staff);
        }

        return staff;
    }

    @Override
    public List<Staff> getByPhone(String phone, String appid, Integer platform) {
        if (platform == null){
            platform = 4;
        }

        if (StringUtils.isEmpty(appid)){
            return staffRepository.findAllByMobileAndPlatformAndDeletedIsFalse(phone, platform);
        }
        return staffRepository.findAllByMobileAndSourceAppIdAndPlatformAndDeletedIsFalse(phone, appid, platform);
    }

    @Override
    public Staff getOpenIDMP(String openid_mp, String appid) {
        return staffRepository.getByOpenidMPAndSourceAppId(openid_mp, appid);
    }

    @Override
    public Staff getOpenIDMA(String openid_ma, String appid) {
        return staffRepository.getByOpenidMAAndSourceAppId(openid_ma, appid);
    }

    @Override
    public Staff getUnionID(String unionId, String appid) {
        return staffRepository.getByUnionidAndSourceAppId(unionId, appid);
    }

    @Override
    @Transactional
    public Staff add(String openid_ma, String openid_mp, String unionid, String sessionKey, String appid, CommonConstant.Platform platform) {

        Staff staff = new Staff();
        staff.setCreated(new Date());

        staff.setOpenidMA(openid_ma);
        staff.setOpenidMP(openid_mp);
        staff.setUnionid(unionid);
        staff.setSourceAppId(appid);
        staff.setSessionKey(sessionKey);
        staff.setPlatform(platform.codeOf());
        staffRepository.save(staff);

        StaffExtInfo extInfo = new StaffExtInfo();
        extInfo.setStaffId(staff.getId());
        staffExtInfoRepository.save(extInfo);

//        StaffVip vip = new StaffVip();
//        vip.setStaffId(staff.getId());
//        userVipRepository.save(vip);

        Organization org = Organization.of(staff.getId());
        orgnizationRepository.save(org);

        staff.setExtInfo(extInfo);
//        staff.setUserVip(vip);

        return staff;
    }

    private static final Pattern CHINA_PATTERN = Pattern.compile("^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$");
    private static final Pattern NUM_PATTERN = Pattern.compile("[0-9]+");

    /**
     * 大陆号码或香港号码均可
     */
    public static boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
        Matcher m = CHINA_PATTERN.matcher(str);
        return m.matches();
    }

    //数字
    public static boolean isNumeric(String string) {
        return NUM_PATTERN.matcher(string).matches();
    }

    @Transactional
    @Override
    public boolean editStaff(Staff user,
                             String areaName,
                             String address,
                             String realName,
                             String areaCode,
                             String areaCodeDesc,
                             String areaPhone,
                             String phoneNumber){

        if(StringUtils.isNotBlank(realName))
            user.setRealName(realName);

        if(StringUtils.isNotBlank(phoneNumber) && isChinaPhoneLegal(phoneNumber))
            user.setMobile(phoneNumber);

        StaffExtInfo extInfo = user.getExtInfo();

        if(extInfo == null) {
            extInfo = new StaffExtInfo();
        }

        Organization organization = staffOrgnization(user);

        if(StringUtils.isNotBlank(areaName))
            organization.setName(areaName);

        if(StringUtils.isNotBlank(address))
            organization.setAddress(address);

        if(StringUtils.isNotBlank(areaCode))
            organization.setPcaCode(areaCode);

        if(StringUtils.isNotBlank(areaCodeDesc))
            organization.setPcaCodeDesc(areaCodeDesc);

        if(StringUtils.isNotBlank(areaPhone) && isNumeric(areaPhone))
            organization.setContactNumber(areaPhone);

        staffRepository.save(user);
        staffExtInfoRepository.save(extInfo);

        return true;
    }

    @Transactional
    @Override
    public Staff updateMaUserInfo(String sessionKey, WxMaUserInfo userInfo, String appid){


        String unionId = userInfo.getUnionId();
        String openId = userInfo.getOpenId();

        //先找到正式账号
        Staff user = null;
        Staff tUser = null;
        if( StringUtils.isNotEmpty(userInfo.getUnionId())){
            user = staffRepository.getByUnionidAndSourceAppIdAndTemporallyIsFalse(userInfo.getUnionId(), appid);
            tUser = staffRepository.getByUnionidAndSourceAppIdAndTemporallyIsTrue(userInfo.getUnionId(), appid);
        }

        if(user == null){  // unionid找不到，就用openid 找
            user = staffRepository.getByOpenidMAAndSourceAppIdAndTemporallyIsFalse(userInfo.getOpenId(), appid);
            tUser = staffRepository.getByOpenidMAAndSourceAppIdAndTemporallyIsTrue(userInfo.getUnionId(), appid);
        }

        if (user == null){
            user = tUser;
            tUser = null;
        }

        if (user == null){
            throw new BusinessException(ErrorCode.STAFF_NOT_EXIST, "没有找到用户");
        }

        if (user != null && user.getTemporally()){  //取消临时账号
            user.setTemporally(false);
        }

        //更新unionid
        user.setUnionid(userInfo.getUnionId());
        user.setOpenidMA(userInfo.getOpenId());

        StaffExtInfo extInfo = user.getExtInfo();
        extInfo.setLanguage(userInfo.getLanguage());
        extInfo.setCity(userInfo.getCity());
        extInfo.setProvince(userInfo.getProvince());
        extInfo.setCountry(userInfo.getCountry());

        //更新用户信息
        user.setHeadImgUrl(userInfo.getAvatarUrl());
        user.setNickName(userInfo.getNickName());
        user.setSexDesc(userInfo.getGender());


        //合并报告数据
        if (user != null && tUser != null){
            evaluateV2Service.transferReports(tUser, user);
            childrenService.transferChildren(tUser, user);

            //清理临时用户
            if (StringUtils.isNotEmpty(tUser.getUnionid())) {
                tUser.setUnionid(tUser.getUnionid() + "__" + System.currentTimeMillis());
            }
            if (StringUtils.isNotEmpty(tUser.getOpenidMA())) {
                tUser.setOpenidMA(tUser.getOpenidMA() + "__" + System.currentTimeMillis());
            }

            staffRepository.save(tUser);
        }

        staffRepository.save(user);
        staffExtInfoRepository.save(extInfo);

        return user;
    }

    @Transactional
    @Override
    public Staff updateMpUserInfo(Staff staff, WxMpUser mpUser){

        staff.setHeadImgUrl(mpUser.getHeadImgUrl());
        staff.setNickName(mpUser.getNickname());
        staff.setSexDesc(mpUser.getSexDesc());

        if (StringUtils.isNotEmpty(mpUser.getUnionId()) && !mpUser.getUnionId().equals(staff.getUnionid())){
            staff.setUnionid(mpUser.getUnionId());
        }

        if (StringUtils.isNotEmpty(mpUser.getOpenId()) && !mpUser.getOpenId().equals(staff.getOpenidMP())){
            staff.setOpenidMP(mpUser.getOpenId());
        }

        StaffExtInfo extInfo = staff.getExtInfo();
        extInfo.setLanguage(mpUser.getLanguage());
        extInfo.setCity(mpUser.getCity());
        extInfo.setProvince(mpUser.getProvince());
        extInfo.setCountry(mpUser.getCountry());

        staffRepository.save(staff);
        staffExtInfoRepository.save(extInfo);

        return staff;
    }

    @Override
    public Staff updatePhoneNumberInfo(String sessionKey, String phoneNum, String appid){
        Staff staff = staffRepository.getBySessionKeyAndSourceAppId(sessionKey, appid);
        staff.setMobile(phoneNum);

        staffRepository.save(staff);

        return staff;
    }

    @Override
    public Staff updatePhoneNumber(Staff staff, String phoneNum){
        staff.setMobile(phoneNum);
        staffRepository.save(staff);
        return staff;
    }

    @Override
    public Staff updateSessionKey(Staff staff, String unionId, String sessionKey){
        if(StringUtils.isNotEmpty(sessionKey))
            staff.setSessionKey(sessionKey);

        if (StringUtils.isNotEmpty(unionId))
            staff.setUnionid(unionId);

        staffRepository.save(staff);

        return staff;
    }

    @Override
    public boolean sendSms(String mobile, Integer sourceType) {
        String code = ModelUtil.getRandomSerial(6);
        System.out.println("========smsCode=" + code);
        cache.produceSmsCode(mobile, code);
        return smsService.sendValidCode(mobile, code, sourceType);
    }

    @Override
    public boolean isTestMobile(String mobile){
        if (mobile.startsWith("1941234")){
            return true;
        }
        if (mobile.equals("15116201157")){
            return true;
        }
        return false;
    }

    @Override
    public boolean checkSmsCode(String mobile, String code) {
        boolean flag = true ;
        String validCode = cache.getSmsCode(mobile);
        if (StringUtils.isBlank(validCode) || !validCode.equals(code)){
            flag = false  ;
        }
        return flag ;
    }

    @Override
    public void clearSmsCode(String mobile){
        cache.clearSmsCode(mobile);
    }

    @Override
    public Organization staffOrgnization(Staff user){
        Organization org = user.getOrg();

        if (org == null){
            org = orgnizationRepository.getByCreatorIdAndBizOrgIsFalse(user.getId());

            if (org == null){
                org = Organization.of(user.getId());
                orgnizationRepository.save(org);
            }
        }

        return org;
    }

    @Override
    public void checkUserVIPStatus(Staff user) {
        // make sure organization valid
        Organization org = staffOrgnization(user);

    }

    @Override
    public boolean isYearsVipOrException(Staff staff){
//        StaffVip vip = getUserVip();
        Organization org = staffOrgnization(staff);

        Date now = new Date();
        if(Objects.nonNull(org) && Objects.nonNull(org.getExpireTime()) && now.compareTo(org.getExpireTime()) != -1){
            throw new BusinessException(ErrorCode.ERROR, "仅包年用户支持这个特性");
        }

        return true;
    }

    @Override
    public boolean isYearsVip(Staff staff){
//        StaffVip vip = getUserVip();
        Organization org = staffOrgnization(staff);

        Date now = new Date();
        if(Objects.nonNull(org) && Objects.nonNull(org.getExpireTime()) && now.compareTo(org.getExpireTime()) == -1){
            return true;
        }

        return false;
    }

    @Override
    public boolean isTimesVip(Staff staff){
        Organization org = staffOrgnization(staff);

        Date now = new Date();
        if(Objects.nonNull(org) && Objects.nonNull(org.getRestCount()) && org.getRestCount() > 0){
            return true;
        }

        return false;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public int transferAllOrganization(){
        List<Staff> staffs = staffRepository.findAll();

        int ret = 0 ;
        for (Staff s : staffs) {
            Organization org = staffOrgnization(s);
            if (org != null){
                ret += 1;
            }
        }

        return ret;
    }
}
